<?php
namespace Admin\Controller;

class DbbakController extends BaseController{
	private $linkid;
	private $sqlid;
	private $record;
	
	public function _initialize(){
		parent::_initialize();
		if (!$this->linkid) @$this->linkid = mysql_connect(C('DB_HOST'),C('DB_USER'),C('DB_PWD')) or $this->failed('连接服务器失败',0,2);
		@mysql_select_db(C('DB_NAME'),$this->linkid) or $this->failed('无法打开数据库：'.mysql_error(),0,2);
		mysql_query('SET NAMES '.C('DB_CHARSET')) or $this->failed('字符集设置错误',0,2);
	}
	
    public function index(){
    	if (IS_POST) $this->bak('Data',date('YmdHis'),I('post.filesize'),I('post.tablename') ? I('post.tablename') : array());
    	$Common = D('Common');
    	$object = $Common->info();
    	$remainder = count($object) % 4;
    	if ($remainder != 0){
    		for ($i=0;$i<4-$remainder;$i++){
    			$object[]['Name'] = '';
    		}
    	}
    	$this->assign('All',$object);
    	$this->display();
    }
    
    private function query($sql){
    	if (!!$this->sqlid = mysql_query($sql,$this->linkid)){
    		return $this->sqlid;
    	}else{
    		$this->failed('SQL语句：'.$sql.'<br>错误信息：'.mysql_error(),0,2);
    	}
    }
    
    private function numFields($sql_id=''){
    	if (!$sql_id) $sql_id = $this->sqlid;
    	return mysql_num_fields($sql_id);
    }
    
    private function nextRecord($sql_id=''){
    	if (!$sql_id) $sql_id = $this->sqlid;
    	return (!!$this->record = mysql_fetch_array($sql_id)) ? $this->record : false;
    }
    
    private function f($name){
    	return $this->record[$name] ? $this->record[$name] : false;
    }
    
    private function getInfo($table){
    	$this->query('SHOW CREATE TABLE '.$table);
    	$this->nextRecord();
    	return "\r\n".str_replace("\n","\r\n",$this->f('Create Table')).";\r\n";
    }
    
    private function getRecord($table,$num_fields){
    	$comma = '';
    	$sql = "INSERT INTO `$table`(`".implode('`,`',array_map('addslashes',array_keys(mysql_fetch_assoc(mysql_query("SELECT * FROM `$table` LIMIT 1",$this->linkid)))))."`) VALUES(";
    	for ($i=0;$i<$num_fields;$i++){
    		$sql .= ($comma."'".addslashes($this->record[$i])."'");
    		$comma = ',';
    	}
    	$sql .= ");\r\n";
    	return $sql;
    }
    
    private function write($sql,$filename){
    	if (!@$fp = fopen($filename,'w+')) $this->failed('文件打开失败！');
    	if (!@fwrite($fp,$sql)) $this->failed('文件写入失败！');
    	if (!@fclose($fp)) $this->failed('文件关闭失败！');
    	return true;
    }
    
    //备份全部表（不分卷）
    private function all($path='',$filename='',$tip=1,$tablestatus=1){
    	if (!$tablesInfo = $this->query('SHOW TABLE STATUS FROM `'.C('DB_NAME')."` LIKE '".C('DB_PREFIX')."%'")) $this->failed('读数据库结构错误！');
    	$sql = "SET NAMES UTF8;\r\n";
    	while ($this->nextRecord($tablesInfo)){
    		$table = $this->f('Name');
    		if ($tablestatus) $sql .= $this->getInfo($table);
    		$this->query("SELECT * FROM $table");
    		$num_fields = $this->numFields();
    		while ($this->nextRecord()){
    			$sql .= $this->getRecord($table,$num_fields);
    		}
    	}
    	$sql = substr($sql,0,-2);
    	$filename .= '_all.sql';
    	if ($this->write($sql,ROOT_PATH.'/'.$path.'/'.$filename) && $tip==1) $this->success(NULL,'全部数据表备份成功，生成备份文件：./'.$path.'/'.$filename.'。',0,2);
    }
    
    //备份全部表（分卷）
    private function allPart($path='',$filename='',$filesize=2000,$tip=1,$tablestatus=1){
    	if (!$tablesInfo = $this->query('SHOW TABLE STATUS FROM `'.C('DB_NAME')."` LIKE '".C('DB_PREFIX')."%'")) $this->failed('读数据库结构错误！');
    	$p = 1;
    	$sql = "SET NAMES UTF8;\r\n";
    	while ($this->nextRecord($tablesInfo)){
    		$table = $this->f('Name');
    		if ($tablestatus) $sql .= $this->getInfo($table);
    		$this->query("SELECT * FROM $table");
    		$num_fields = $this->numFields();
    		while ($this->nextRecord()){
    			$sql .= $this->getRecord($table,$num_fields);
    			if (strlen($sql) >= $filesize*1024){
    				$sql = substr($sql,0,-2);
    				$filename2 = $filename.'_all_part'.$p.'.sql';
    				if ($this->write($sql,$path.'/'.$filename2)){
    					$info[] = $filename2;
    				}else{
    					$info[] = '备份'.$filename2.'失败';
    				}
    				$p++;
    				$sql = '';
    			}
    		}
    	}
    	if ($sql != ''){
    		$sql = substr($sql,0,-2);
    		$filename .= '_all_part'.$p.'.sql';
    		if ($this->write($sql,ROOT_PATH.'/'.$path.'/'.$filename)) $info[] = $filename;
    	}
    	if ($tip==1) $this->success(NULL,'全部数据表备份成功，已保存到./'.$path.'目录，生成备份文件：<br>'.implode('<br>',$info),0,2);
    }
    
    //备份自定义多表（不分卷）
    private function n($path='',$filename='',$tables=array(),$tip=1,$tablestatus=1){
    	$sql = "SET NAMES UTF8;\r\n";
    	foreach ($tables as $value){
    		if ($tablestatus) $sql .= $this->getInfo($value);
    		$this->query('SELECT * FROM '.$value);
    		$num_fields = $this->numFields();
    		while ($this->nextRecord()){
    			$sql .= $this->getRecord($value,$num_fields);
    		}
    	}
    	$sql = substr($sql,0,-2);
    	$filename .= '_n.sql';
    	if ($this->write($sql,ROOT_PATH.'/'.$path.'/'.$filename) && $tip==1) $this->success(NULL,'数据表备份成功，已保存到./'.$path.'目录，生成备份文件：'.$filename,0,2);
    }
    
    //备份自定义多表（分卷）
    private function nPart($path='',$filename='',$filesize=2000,$tables=array(),$tip=1,$tablestatus=1){
    	$p = 1;
    	$sql = "SET NAMES UTF8;\r\n";
    	foreach ($tables as $value){
    		if ($tablestatus) $sql .= $this->getInfo($value);
    		$this->query('SELECT * FROM '.$value);
    		$num_fields = $this->numFields();
    		while ($this->nextRecord()){
    			$sql .= $this->getRecord($value,$num_fields);
    			if (strlen($sql) >= $filesize*1024){
    				$sql = substr($sql,0,-2);
    				$filename2 = $filename.'_n_part'.$p.'.sql';
    				if ($this->write($sql,$path.'/'.$filename2)){
    					$info[] = $filename2;
    				}else{
    					$info[] = '备份表-'.$value.'-失败';
    				}
    				$p++;
    				$sql = '';
    			}
    		}
    	}
    	if ($sql != ''){
    		$sql = substr($sql,0,-2);
    		$filename .= '_n_part'.$p.'.sql';
    		if ($this->write($sql,ROOT_PATH.'/'.$path.'/'.$filename)) $info[] = $filename;
    	}
    	if ($tip==1) $this->success(NULL,'数据表备份成功，已保存到./'.$path.'目录，生成备份文件：<br>'.implode('<br>',$info),0,2);
    }
    
    public function bak($path='',$filename='',$filesize=2000,$tables=array(),$tip=1,$tablestatus=1){
    	if (empty($path)) $this->failed('请设置保存数据库文件的目录！');
    	if (!is_dir($path)) $this->failed($path.'目录不存在，请手工创建！');
    	if (empty($filename)) $this->failed('请设置数据库文件名！');
    	if (!is_numeric($filesize)) $this->failed('分卷大小必须是数字！');
    	if (!is_array($tables)) $this->failed('数据表必须是数组！');
    	$path = str_replace('\\','/',$path);
		
    	count($tables)==0 ? empty($filesize) ? $this->all($path,$filename,$tip,$tablestatus) : $this->allPart($path,$filename,$filesize,$tip,$tablestatus) : empty($filesize) ? $this->n($path,$filename,$tables,$tip,$tablestatus) : $this->nPart($path,$filename,$filesize,$tables,$tip,$tablestatus);
    }
}